#pragma once
#include <math.h>

extern const float EPSILON;

template <class T>
class Vector4
{
public:
    // constructor/destructor
    Vector4() { x = 0; y = 0; z = 0; w = 1; }
	Vector4( T _x, T _y, T _z, T _w ) :
        x(_x), y(_y), z(_z), w(_w)
    {}
    ~Vector4() {}

    // copy operations
    Vector4(const Vector4<T>& other)
	{
		x = other.x;
		y = other.y;
		z = other.z;
		w = other.w;
	}
    Vector4<T>& operator=(const Vector4<T>& other)
	{
		x = other.x;
		y = other.y;
		z = other.z;
		w = other.w;
		return (*this);
	}

    inline T& operator[](unsigned int i);
    inline T length() const;
    inline T lengthSquared() const;

    //T Distance( const Vector4& p0, const Vector4& p1 );
    //T DistanceSquared( const Vector4& p0, const Vector4& p1 );

    // comparison
    inline bool operator==(const Vector4<T>& other) const;
    inline bool operator!=(const Vector4<T>& other) const;
    inline bool isNull() const;

    // manipulators
    inline void set( T _x, T _y, T _z, T _w );
    /**
    @remark sets all elements to 0
    */ 
	inline void setNull();
	/**
	@remark sets to unit vector
	*/
    inline void normalize();

    // operate on xyz only, otherwise use operator
	inline Vector4<T>& addequal(const Vector4<T>& rhs);
	inline Vector4<T>& minusequal(const Vector4<T>& rhs);

    // addition/subtraction
    inline Vector4<T> operator+(const Vector4<T>& other) const;
    inline Vector4<T>& operator+=(const Vector4<T>& other);
    inline Vector4<T> operator-(const Vector4<T>& other) const;
    inline Vector4<T>& operator-=(const Vector4<T>& other);
    inline Vector4<T> operator-() const;

    // scalar multiplication
    inline Vector4<T> operator*(T scalar) const;
	inline Vector4<T>& operator*=(T scalar);
    //Vector4 operator*( float scalar, const Vector4& vector );
    //Vector4 operator/( float scalar );
    //Vector4&          operator/=( float scalar );

    // dot product/cross product
    inline T dot(const Vector4<T>& vector) const;
    static T dot(const Vector4<T>& vector1, const Vector4<T>& vector2);

    // member variables
    T x, y, z, w;
};

#include "Vector4.inl"

typedef Vector4<float> vec4f;